package com.cskaoyan.service;

import com.cskaoyan.bean.MarketCouponUser;
import com.cskaoyan.bean.MarketOrder;
import com.cskaoyan.bean.MarketOrderExample;
import com.cskaoyan.bean.MarketOrderGoods;
import com.cskaoyan.bean.common.BaseRespVo;
import com.cskaoyan.bean.common.CommonData;
import com.cskaoyan.bean.vo.UserVo;
import com.cskaoyan.mapper.MarketOrderMapper;
import com.cskaoyan.util.*;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.util.StringUtil;
import org.apache.ibatis.session.SqlSessionFactory;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author stone
 * @date 2023/03/17 19:21
 */
public class OrderServiceImpl implements OrderService {

    private OrderGoodsService orderGoodsService = new OrderGoodsServiceImpl();
    private UserService userService = new UserServiceImpl();
    private GoodsProductService productService = new GoodsProductServiceImpl();
    private CouponUserService couponUserService = new CouponUserServiceImpl();
    private LogService logService = new LogServiceImpl();

    SqlSessionFactory sqlSessionFactory = MyBatisUtil.getSqlSessionFactory();
    @Override
    public CommonData list(Integer userId, String orderSn, Date start, Date end, List<Short> orderStatusArray, Integer page, Integer limit, String sort, String order) {
        MarketOrderExample example = new MarketOrderExample();
        MarketOrderExample.Criteria criteria = example.createCriteria();

        if (userId != null) {
            criteria.andUserIdEqualTo(userId);
        }
        if (!StringUtil.isEmpty(orderSn)) {
            criteria.andOrderSnEqualTo(orderSn);
        }
        if(start != null){
            criteria.andAddTimeGreaterThanOrEqualTo(start);
        }
        if(end != null){
            criteria.andAddTimeLessThanOrEqualTo(end);
        }
        if (orderStatusArray != null && orderStatusArray.size() != 0) {
            criteria.andOrderStatusIn(orderStatusArray);
        }
        criteria.andDeletedEqualTo(false);

        if (!StringUtil.isEmpty(sort) && !StringUtil.isEmpty(order)) {
            example.setOrderByClause(sort + " " + order);
        }

        MarketOrderMapper orderMapper = sqlSessionFactory.openSession().getMapper(MarketOrderMapper.class);
        PageHelper.startPage(page, limit);
        List<MarketOrder> marketOrders = orderMapper.selectByExample(example);
        return CommonData.data(new PageInfo(marketOrders));
    }

    @Override
    public Map<String, Object> detail(Integer id) {
        MarketOrder order = findById(id);
        List<MarketOrderGoods> orderGoods = orderGoodsService.queryByOid(id);
        UserVo user = userService.findUserVoById(order.getUserId());
        Map<String, Object> data = new HashMap<>();
        data.put("order", order);
        data.put("orderGoods", orderGoods);
        data.put("user", user);
        return data;
    }

    @Override
    public BaseRespVo refund(Integer orderId, String refundMoney) {
        if (orderId == null) {
            return BaseRespVo.badArgument();
        }
        if (StringUtil.isEmpty(refundMoney)) {
            return BaseRespVo.badArgument();
        }

        MarketOrder order = findById(orderId);
        if (order == null) {
            return BaseRespVo.badArgument();
        }

        if (order.getActualPrice().compareTo(new BigDecimal(refundMoney)) != 0) {
            return BaseRespVo.badArgument();
        }

        // 如果订单不是退款状态，则不能退款
        if (!order.getOrderStatus().equals(OrderConstant.STATUS_REFUND)) {
            return BaseRespVo.fail(620, "订单不能确认收货");
        }
        // 修改数据库中的数据，需要增加事务
        TransactionUtil.startTransaction();
        // 设置订单取消状态
        order.setOrderStatus(OrderConstant.STATUS_REFUND_CONFIRM);
        Date now = new Date();
        order.setEndTime(now);
        // 记录订单退款相关信息
        order.setRefundAmount(order.getActualPrice());
        order.setRefundType("微信退款接口");
        order.setRefundTime(now);
        if (updateWithOptimisticLocker(order) == 0) {
            throw new RuntimeException("更新数据已失效");
        }

        // 商品货品数量增加 ->增加库存
        List<MarketOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);
        for (MarketOrderGoods orderGoods : orderGoodsList) {
            Integer productId = orderGoods.getProductId();
            Short number = orderGoods.getNumber();
            if (productService.addStock(productId, number) == 0) {
                throw new RuntimeException("商品货品库存增加失败");
            }
        }

        // 返还优惠券
        List<MarketCouponUser> couponUsers = couponUserService.findByOid(orderId);
        for (MarketCouponUser couponUser: couponUsers) {
            // 优惠券状态设置为可使用
            couponUser.setStatus(CouponUserConstant.STATUS_USABLE);
            couponUser.setUpdateTime(new Date());
            couponUserService.update(couponUser);
        }


        logService.logOrderSucceed("退款", "订单编号 " + order.getOrderSn());
        TransactionUtil.commit();
        return BaseRespVo.ok();
    }

    @Override
    public BaseRespVo ship(Integer orderId, String shipSn, String shipChannel) {
        if (orderId == null || shipSn == null || shipChannel == null) {
            return BaseRespVo.badArgument();
        }

        MarketOrder order = findById(orderId);
        if (order == null) {
            return BaseRespVo.badArgument();
        }

        // 如果订单不是已付款状态，则不能发货
        if (!order.getOrderStatus().equals(OrderConstant.STATUS_PAY)) {
            return BaseRespVo.fail(620, "订单不能确认收货");
        }

        order.setOrderStatus(OrderConstant.STATUS_SHIP);
        order.setShipSn(shipSn);
        order.setShipChannel(shipChannel);
        order.setShipTime(new Date());
        TransactionUtil.startTransaction();
        if (updateWithOptimisticLocker(order) == 0) {
            return BaseRespVo.expired();
        }


        logService.logOrderSucceed("发货", "订单编号 " + order.getOrderSn());
        TransactionUtil.commit();
        return BaseRespVo.ok();
    }

    @Override
    public BaseRespVo remove(Integer orderId) {
        TransactionUtil.startTransaction();
        MarketOrder order = this.findById(orderId);
        if (order == null) {
            return BaseRespVo.badArgument();
        }

        // 如果订单不是关闭状态(已取消、系统取消、已退款、用户已确认、系统已确认)，则不能删除
        Short status = order.getOrderStatus();
        if (!status.equals(OrderConstant.STATUS_CANCEL) && !status.equals(OrderConstant.STATUS_AUTO_CANCEL) &&
                !status.equals(OrderConstant.STATUS_CONFIRM) &&!status.equals(OrderConstant.STATUS_AUTO_CONFIRM) &&
                !status.equals(OrderConstant.STATUS_REFUND_CONFIRM)) {
            return BaseRespVo.fail(623, "订单不能删除");
        }
        // 删除订单
        this.deleteById(orderId);
        // 删除订单商品
        orderGoodsService.deleteByOrderId(orderId);
        logService.logOrderSucceed("删除", "订单编号 " + order.getOrderSn());
        TransactionUtil.commit();
        return BaseRespVo.ok();
    }

    @Override
    public int deleteById(Integer orderId) {
        MarketOrderMapper orderMapper = TransactionUtil.getMapper(MarketOrderMapper.class);
        MarketOrder marketOrder = new MarketOrder();
        marketOrder.setId(orderId);
        marketOrder.setDeleted(true);
        int update = orderMapper.updateByPrimaryKeySelective(marketOrder);
        return update;
    }

    private int updateWithOptimisticLocker(MarketOrder order) {
        Date preUpdateTime = order.getUpdateTime();
        order.setUpdateTime(new Date());
        MarketOrderMapper orderMapper = TransactionUtil.getSqlSession().getMapper(MarketOrderMapper.class);
        int update = orderMapper.updateWithOptimisticLocker(preUpdateTime, order);
        return update;
    }

    private MarketOrder findById(Integer orderId) {
        MarketOrderMapper orderMapper = sqlSessionFactory.openSession().getMapper(MarketOrderMapper.class);
        return orderMapper.selectByPrimaryKey(orderId);
    }
}
